using System;
using System.Collections.Generic;
using System.Linq;

namespace MT5Trade.Models
{
    /// <summary>
    /// Delta中性对冲策略实现类
    /// </summary>
    public class DeltaNeutralHedgeStrategy
    {
        private readonly GapAnalyzer _gapAnalyzer;
        private readonly HedgeRatioCalculator _hedgeRatioCalculator;

        // Beta系数相关常量
        private const int MIN_DATA_POINTS_FOR_BETA = 50;
        private const double DEFAULT_BETA_VALUE = 1.0;
        private const double CORRELATION_THRESHOLD = 0.7;
        private const double DELTA_NEUTRALITY_TOLERANCE = 0.05; // 5%的Delta偏差容忍度

        // 对冲参数
        private const double MIN_HEDGE_RATIO = 0.1;
        private const double MAX_HEDGE_RATIO = 2.0;
        private const double DEFAULT_HEDGE_RATIO = 1.0;

        public DeltaNeutralHedgeStrategy(GapAnalyzer gapAnalyzer, HedgeRatioCalculator hedgeRatioCalculator)
        {
            _gapAnalyzer = gapAnalyzer ?? throw new ArgumentNullException(nameof(gapAnalyzer));
            _hedgeRatioCalculator = hedgeRatioCalculator ?? throw new ArgumentNullException(nameof(hedgeRatioCalculator));
        }

        /// <summary>
        /// 相关性分析结果
        /// </summary>
        public class CorrelationAnalysisResult
        {
            public double CorrelationCoefficient { get; set; }
            public double Beta { get; set; }
            public double Alpha { get; set; }
            public double RSquared { get; set; }
            public int DataPointsCount { get; set; }
            public string Significance { get; set; }
            public DateTime StartDate { get; set; }
            public DateTime EndDate { get; set; }
            public bool IsReliable => DataPointsCount >= MIN_DATA_POINTS_FOR_BETA && Math.Abs(CorrelationCoefficient) >= 0.3;
        }

        /// <summary>
        /// Delta中性对冲结果
        /// </summary>
        public class DeltaNeutralHedgeResult
        {
            public double OptimalHedgeRatio { get; set; }
            public double DeltaExposure { get; set; }
            public double HedgeEffectiveness { get; set; }
            public double RiskReduction { get; set; }
            public double HedgeCost { get; set; }
            public bool IsDeltaNeutral => Math.Abs(DeltaExposure) <= DELTA_NEUTRALITY_TOLERANCE;
            public string Strategy { get; set; }
            public List<string> Warnings { get; set; } = new List<string>();
            public Dictionary<string, double> RiskMetrics { get; set; } = new Dictionary<string, double>();
        }

        /// <summary>
        /// 动态对冲调整建议
        /// </summary>
        public class DynamicHedgeAdjustment
        {
            public double CurrentHedgeRatio { get; set; }
            public double RecommendedHedgeRatio { get; set; }
            public double AdjustmentMagnitude => Math.Abs(RecommendedHedgeRatio - CurrentHedgeRatio);
            public string AdjustmentDirection => RecommendedHedgeRatio > CurrentHedgeRatio ? "增加" : "减少";
            public string Urgency { get; set; }
            public string Reason { get; set; }
            public double ExpectedRiskReduction { get; set; }
        }

        /// <summary>
        /// 计算两个时间序列的相关性分析
        /// </summary>
        public CorrelationAnalysisResult CalculateCorrelationAnalysis(
            List<MarketDataPoint> primarySeries, 
            List<MarketDataPoint> hedgeSeries, 
            int lookbackDays = 60)
        {
            if (primarySeries == null || hedgeSeries == null)
                throw new ArgumentNullException("数据序列不能为空");

            var cutoffDate = DateTime.Now.AddDays(-lookbackDays);
            var primary = primarySeries.Where(p => p.Time >= cutoffDate).OrderBy(p => p.Time).ToList();
            var hedge = hedgeSeries.Where(h => h.Time >= cutoffDate).OrderBy(h => h.Time).ToList();

            if (primary.Count < MIN_DATA_POINTS_FOR_BETA || hedge.Count < MIN_DATA_POINTS_FOR_BETA)
            {
                return new CorrelationAnalysisResult
                {
                    CorrelationCoefficient = 0,
                    Beta = DEFAULT_BETA_VALUE,
                    Alpha = 0,
                    RSquared = 0,
                    DataPointsCount = Math.Min(primary.Count, hedge.Count),
                    Significance = "数据不足",
                    StartDate = primary.FirstOrDefault()?.Time ?? DateTime.Now,
                    EndDate = primary.LastOrDefault()?.Time ?? DateTime.Now
                };
            }

            // 计算收益率
            var primaryReturns = CalculateReturns(primary);
            var hedgeReturns = CalculateReturns(hedge);

            // 对齐时间序列
            var alignedData = AlignTimeSeries(primaryReturns, hedgeReturns);
            
            if (alignedData.Count < MIN_DATA_POINTS_FOR_BETA)
            {
                return new CorrelationAnalysisResult
                {
                    CorrelationCoefficient = 0,
                    Beta = DEFAULT_BETA_VALUE,
                    DataPointsCount = alignedData.Count,
                    Significance = "对齐后数据不足"
                };
            }

            var xValues = alignedData.Select(d => d.hedge).ToArray();
            var yValues = alignedData.Select(d => d.primary).ToArray();

            // 计算统计指标
            var correlation = CalculateCorrelation(xValues, yValues);
            var regression = CalculateLinearRegression(xValues, yValues);

            return new CorrelationAnalysisResult
            {
                CorrelationCoefficient = correlation,
                Beta = regression.slope,
                Alpha = regression.intercept,
                RSquared = regression.rSquared,
                DataPointsCount = alignedData.Count,
                Significance = GetCorrelationSignificance(correlation, alignedData.Count),
                StartDate = primary.First().Time,
                EndDate = primary.Last().Time
            };
        }

        /// <summary>
        /// 实现Delta中性对冲策略
        /// </summary>
        public DeltaNeutralHedgeResult ImplementDeltaNeutralHedge(
            GapData gapData, 
            List<MarketDataPoint> primaryData,
            List<MarketDataPoint> hedgeData,
            double currentPosition,
            double targetBs = 0)
        {
            var result = new DeltaNeutralHedgeResult
            {
                Strategy = "Delta中性对冲"
            };

            // 1. 进行相关性分析
            var correlationAnalysis = CalculateCorrelationAnalysis(primaryData, hedgeData);
            
            if (!correlationAnalysis.IsReliable)
            {
                result.Warnings.Add($"相关性分析不可靠：数据点{correlationAnalysis.DataPointsCount}个，相关系数{correlationAnalysis.CorrelationCoefficient:F3}");
            }

            // 2. 计算基于缺口类型的基础对冲比例
            var gapHedgeResult = _hedgeRatioCalculator.CalculateHedgeRatio(gapData, primaryData);
            
            // 3. 计算Delta中性对冲比例
            double deltaNeutralRatio = CalculateDeltaNeutralRatio(
                correlationAnalysis.Beta, 
                gapHedgeResult.RecommendedRatio,
                gapData,
                targetBs);

            // 4. 应用风险调整
            deltaNeutralRatio = ApplyRiskAdjustments(
                deltaNeutralRatio, 
                correlationAnalysis, 
                gapData, 
                currentPosition);

            // 5. 计算Delta敞口
            double deltaExposure = CalculateDeltaExposure(currentPosition, deltaNeutralRatio, correlationAnalysis.Beta);

            // 6. 评估对冲效果
            double hedgeEffectiveness = EstimateHedgeEffectiveness(correlationAnalysis, gapHedgeResult);
            double riskReduction = EstimateRiskReduction(correlationAnalysis, deltaNeutralRatio);
            double hedgeCost = EstimateHedgeCost(deltaNeutralRatio, gapData);

            // 7. 设置结果
            result.OptimalHedgeRatio = Math.Round(deltaNeutralRatio, 4);
            result.DeltaExposure = Math.Round(deltaExposure, 4);
            result.HedgeEffectiveness = Math.Round(hedgeEffectiveness, 4);
            result.RiskReduction = Math.Round(riskReduction, 4);
            result.HedgeCost = Math.Round(hedgeCost, 4);

            // 8. 设置风险指标
            result.RiskMetrics["Beta"] = Math.Round(correlationAnalysis.Beta, 4);
            result.RiskMetrics["Correlation"] = Math.Round(correlationAnalysis.CorrelationCoefficient, 4);
            result.RiskMetrics["R²"] = Math.Round(correlationAnalysis.RSquared, 4);
            result.RiskMetrics["Gap填补概率"] = Math.Round(gapData.FillProbability, 4);

            // 9. 生成警告
            GenerateHedgeWarnings(result, correlationAnalysis, gapData);

            return result;
        }

        /// <summary>
        /// 计算动态对冲调整建议
        /// </summary>
        public DynamicHedgeAdjustment CalculateDynamicHedgeAdjustment(
            double currentHedgeRatio,
            GapData latestGap,
            List<MarketDataPoint> recentData,
            double currentVolatility)
        {
            var adjustment = new DynamicHedgeAdjustment
            {
                CurrentHedgeRatio = currentHedgeRatio
            };

            // 基于最新缺口信息重新计算推荐对冲比例
            var latestHedgeResult = _hedgeRatioCalculator.CalculateHedgeRatio(latestGap, recentData);
            
            // 考虑波动率调整
            double volatilityAdjustment = CalculateVolatilityAdjustment(currentVolatility);
            double adjustedRatio = latestHedgeResult.RecommendedRatio * volatilityAdjustment;
            
            adjustment.RecommendedHedgeRatio = Math.Max(MIN_HEDGE_RATIO, 
                Math.Min(MAX_HEDGE_RATIO, adjustedRatio));

            // 评估调整紧急度
            double adjustmentMagnitude = Math.Abs(adjustment.RecommendedHedgeRatio - currentHedgeRatio);
            
            if (adjustmentMagnitude > 0.3)
                adjustment.Urgency = "高";
            else if (adjustmentMagnitude > 0.1)
                adjustment.Urgency = "中";
            else
                adjustment.Urgency = "低";

            // 生成调整原因
            adjustment.Reason = GenerateAdjustmentReason(latestGap, currentVolatility, adjustmentMagnitude);
            
            // 估算预期风险降低
            adjustment.ExpectedRiskReduction = EstimateAdjustmentBenefit(
                currentHedgeRatio, 
                adjustment.RecommendedHedgeRatio, 
                latestGap);

            return adjustment;
        }

        #region 私有辅助方法

        private List<(DateTime time, double value)> CalculateReturns(List<MarketDataPoint> data)
        {
            var returns = new List<(DateTime, double)>();
            
            for (int i = 1; i < data.Count; i++)
            {
                var currentPrice = data[i].Close;
                var previousPrice = data[i - 1].Close;
                var return_ = (currentPrice - previousPrice) / previousPrice;
                returns.Add((data[i].Time, return_));
            }
            
            return returns;
        }

        private List<(double primary, double hedge)> AlignTimeSeries(
            List<(DateTime time, double value)> primaryReturns,
            List<(DateTime time, double value)> hedgeReturns)
        {
            var aligned = new List<(double, double)>();
            var hedgeDict = hedgeReturns.ToDictionary(h => h.time.Date, h => h.value);
            
            foreach (var primary in primaryReturns)
            {
                if (hedgeDict.TryGetValue(primary.time.Date, out var hedgeValue))
                {
                    aligned.Add((primary.value, hedgeValue));
                }
            }
            
            return aligned;
        }

        private double CalculateCorrelation(double[] x, double[] y)
        {
            if (x.Length != y.Length || x.Length == 0)
                return 0;

            var meanX = x.Average();
            var meanY = y.Average();
            
            var numerator = x.Zip(y, (xi, yi) => (xi - meanX) * (yi - meanY)).Sum();
            var sumXSquared = x.Sum(xi => Math.Pow(xi - meanX, 2));
            var sumYSquared = y.Sum(yi => Math.Pow(yi - meanY, 2));
            
            var denominator = Math.Sqrt(sumXSquared * sumYSquared);
            
            return denominator == 0 ? 0 : numerator / denominator;
        }

        private (double slope, double intercept, double rSquared) CalculateLinearRegression(double[] x, double[] y)
        {
            if (x.Length != y.Length || x.Length == 0)
                return (0, 0, 0);

            var meanX = x.Average();
            var meanY = y.Average();
            
            var numerator = x.Zip(y, (xi, yi) => (xi - meanX) * (yi - meanY)).Sum();
            var denominator = x.Sum(xi => Math.Pow(xi - meanX, 2));
            
            var slope = denominator == 0 ? 0 : numerator / denominator;
            var intercept = meanY - slope * meanX;
            
            // 计算R²
            var predicted = x.Select(xi => slope * xi + intercept).ToArray();
            var ssRes = y.Zip(predicted, (actual, pred) => Math.Pow(actual - pred, 2)).Sum();
            var ssTot = y.Sum(yi => Math.Pow(yi - meanY, 2));
            var rSquared = ssTot == 0 ? 0 : 1 - (ssRes / ssTot);
            
            return (slope, intercept, rSquared);
        }

        private string GetCorrelationSignificance(double correlation, int sampleSize)
        {
            var absCorrelation = Math.Abs(correlation);
            
            if (sampleSize < 30)
                return "样本量小";
            else if (absCorrelation >= 0.7)
                return "强相关";
            else if (absCorrelation >= 0.4)
                return "中等相关";
            else if (absCorrelation >= 0.2)
                return "弱相关";
            else
                return "无相关";
        }

        private double CalculateDeltaNeutralRatio(double beta, double baseHedgeRatio, GapData gapData, double targetBs)
        {
            // 基础Delta中性比例 = Beta系数 × 基础对冲比例
            double deltaNeutralRatio = beta * baseHedgeRatio;
            
            // 根据缺口类型进行调整
            double gapTypeAdjustment = GetGapTypeAdjustment(gapData.Type);
            deltaNeutralRatio *= gapTypeAdjustment;
            
            // 如果有目标Bs设置，进行调整
            if (targetBs > 0)
            {
                double bsAdjustment = Math.Min(2.0, Math.Max(0.5, targetBs / 100.0));
                deltaNeutralRatio *= bsAdjustment;
            }
            
            return Math.Max(MIN_HEDGE_RATIO, Math.Min(MAX_HEDGE_RATIO, deltaNeutralRatio));
        }

        private double GetGapTypeAdjustment(GapType gapType)
        {
            return gapType switch
            {
                GapType.Common => 1.1,      // 普通缺口，略微增加对冲
                GapType.Breakaway => 0.8,   // 突破缺口，减少对冲
                GapType.Runaway => 0.7,     // 持续缺口，大幅减少对冲
                GapType.Exhaustion => 1.2,  // 衰竭缺口，显著增加对冲
                _ => 1.0
            };
        }

        private double ApplyRiskAdjustments(double baseRatio, CorrelationAnalysisResult correlation, GapData gapData, double currentPosition)
        {
            double adjustedRatio = baseRatio;
            
            // 相关性调整
            if (Math.Abs(correlation.CorrelationCoefficient) < 0.3)
            {
                adjustedRatio *= 0.8; // 相关性弱时减少对冲
            }
            
            // 缺口大小调整
            if (gapData.GapPercentage > 2.0) // 大缺口
            {
                adjustedRatio *= 1.2;
            }
            else if (gapData.GapPercentage < 0.5) // 小缺口
            {
                adjustedRatio *= 0.9;
            }
            
            // 仓位规模调整
            if (Math.Abs(currentPosition) > 10.0) // 大仓位
            {
                adjustedRatio *= 1.1;
            }
            
            return Math.Max(MIN_HEDGE_RATIO, Math.Min(MAX_HEDGE_RATIO, adjustedRatio));
        }

        private double CalculateDeltaExposure(double position, double hedgeRatio, double beta)
        {
            // Delta敞口 = 净仓位 - (对冲仓位 × Beta)
            double hedgePosition = position * hedgeRatio;
            return position - (hedgePosition * beta);
        }

        private double EstimateHedgeEffectiveness(CorrelationAnalysisResult correlation, HedgeRatioResult gapHedgeResult)
        {
            // 对冲有效性 = 相关系数² × 缺口对冲成功率
            return Math.Abs(correlation.CorrelationCoefficient) * correlation.RSquared * gapHedgeResult.SuccessProbability;
        }

        private double EstimateRiskReduction(CorrelationAnalysisResult correlation, double hedgeRatio)
        {
            // 风险降低 = 1 - √(1 - 相关系数² × 对冲比例²)
            var riskReductionFactor = correlation.RSquared * Math.Pow(hedgeRatio, 2);
            return Math.Min(0.95, Math.Sqrt(riskReductionFactor)); // 最大95%的风险降低
        }

        private double EstimateHedgeCost(double hedgeRatio, GapData gapData)
        {
            // 简化的对冲成本估算 = 对冲比例 × 缺口大小 × 成本系数
            const double costCoefficient = 0.001; // 0.1%的基础成本
            return hedgeRatio * gapData.GapPercentage * costCoefficient;
        }

        private void GenerateHedgeWarnings(DeltaNeutralHedgeResult result, CorrelationAnalysisResult correlation, GapData gapData)
        {
            if (Math.Abs(correlation.CorrelationCoefficient) < 0.3)
            {
                result.Warnings.Add($"相关性较弱({correlation.CorrelationCoefficient:F3})，对冲效果可能有限");
            }
            
            if (correlation.DataPointsCount < MIN_DATA_POINTS_FOR_BETA)
            {
                result.Warnings.Add($"历史数据不足({correlation.DataPointsCount}个数据点)，Beta估算可能不准确");
            }
            
            if (result.OptimalHedgeRatio > 1.5)
            {
                result.Warnings.Add($"对冲比例较高({result.OptimalHedgeRatio:F2})，请注意过度对冲风险");
            }
            
            if (!result.IsDeltaNeutral)
            {
                result.Warnings.Add($"未达到Delta中性({result.DeltaExposure:F3})，可能仍存在方向性风险");
            }
        }

        private double CalculateVolatilityAdjustment(double currentVolatility)
        {
            // 根据当前波动率调整对冲比例
            const double normalVolatility = 0.02; // 2%的正常波动率
            
            if (currentVolatility > normalVolatility * 2)
                return 1.3; // 高波动时增加对冲
            else if (currentVolatility > normalVolatility * 1.5)
                return 1.1; // 中等波动时略微增加
            else if (currentVolatility < normalVolatility * 0.5)
                return 0.8; // 低波动时减少对冲
            else
                return 1.0; // 正常波动保持不变
        }

        private string GenerateAdjustmentReason(GapData gapData, double volatility, double adjustmentMagnitude)
        {
            var reasons = new List<string>();
            
            if (gapData.Type != GapType.None)
            {
                reasons.Add($"检测到{gapData.Type}缺口");
            }
            
            if (volatility > 0.03)
            {
                reasons.Add("市场波动率上升");
            }
            
            if (adjustmentMagnitude > 0.2)
            {
                reasons.Add("风险敞口显著变化");
            }
            
            return reasons.Count > 0 ? string.Join("，", reasons) : "市场条件变化";
        }

        private double EstimateAdjustmentBenefit(double currentRatio, double recommendedRatio, GapData gapData)
        {
            // 简化的调整收益估算
            double adjustmentBenefit = Math.Abs(recommendedRatio - currentRatio) * gapData.FillProbability * 0.1;
            return Math.Min(0.5, adjustmentBenefit); // 最大50%的风险降低
        }

        #endregion
    }
}


